package de.pernpas.stadtfuehrer.service;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;

import de.pernpas.stadtfuehrer.entity.EMF;
import de.pernpas.stadtfuehrer.entity.Role;
import de.pernpas.stadtfuehrer.entity.User;
import de.pernpas.stadtfuehrer.exception.BadPasswordException;

public class UserServiceImpl implements UserService {

	private static final Logger logger = Logger.getLogger(UserServiceImpl.class.getName());

	private static final String PSEUDONYM = "pseudonym";

	public UserServiceImpl() {
		super();
	}

	@Override
	public void create(User user) {
		EntityManager em = EMF.get().createEntityManager();
		PasswordEncryptionService pes = new PasswordEncryptionService();
		
		if(isFirstUser()){
			user.getRoles().add(Role.ADMIN);
		}
		
		try {
			// Encrypt Password
			byte[] salt = pes.generateSalt();
			byte[] encryptedPassword = pes.getEncryptedPassword(user.getPassword(), salt);
			user.setSalt(salt);
			user.setPasswordEncrypted(encryptedPassword);
			em.persist(user);
		} catch (Exception e) {
			logger.log(Level.SEVERE, e.getMessage(), e);
		} finally {
			if (em != null)
				em.close();
		}
	}

	private boolean isFirstUser() {
		if(retrieveAllUser().size() == 0)
			return true;
		else
			return false;
	}

	@Override
	public User retrieve() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void update(User user) {
		EntityManager em = EMF.get().createEntityManager();
		em.merge(user);
		em.close();
	}

	@Override
	public void delete(User user) {
		EntityManager em = EMF.get().createEntityManager();
		User delete = em.find(User.class, user.getKey());
		em.remove(delete);
		em.close();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<User> retrieveAllUser() {
		List<User> result = new ArrayList<User>();
		EntityManager em = EMF.get().createEntityManager();
		Query query = em.createNamedQuery("allUser");
		result = query.getResultList();
		// becouse of Bug
		// http://code.google.com/p/datanucleus-appengine/issues/detail?id=24 I
		// have to call size()
		result.size();
		em.close();
		return new ArrayList<User>(result);
	}

	@Override
	public User getUser(String pseudonym, String password) throws BadPasswordException {
		User result = null;
		EntityManager em = EMF.get().createEntityManager();
		Query query = em.createQuery("Select u from " + User.class.getSimpleName() + " u where u.pseudonym = :"
				+ PSEUDONYM);
		query.setParameter(PSEUDONYM, pseudonym);
		User user;
		try {
			user = (User) query.getSingleResult();
			
			PasswordEncryptionService pes = new PasswordEncryptionService();
			try {
				if (pes.authenticate(password, user.getPasswordEncrypted(), user.getSalt())) {
					result = user;
				} else {
					throw new BadPasswordException("Bad Password");
				}
			} catch (Exception e) {
				logger.log(Level.SEVERE, e.getMessage(), e);
			}
		} catch (NoResultException nre) {
			logger.log(Level.INFO, nre.getMessage(), nre);
		}
		em.close();
		return result;
	}

	@Override
	public boolean hasUserRole(User u, Role r) {
		boolean result = false;
		for (Role userRole : u.getRoles()) {
			if (userRole == r) {
				result = true;
				break;
			}
		}
		return result;
	}
}
